package com.rfid.assistant;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;

import com.rfid.DirectoryBean;
import com.rfid.event.SendStatus;
import com.rfid.sockethelper.IOHelper;
import com.rfid.sockethelper.SocketBase;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public enum  BluetoothManager implements SocketBase.OnReceiveListener {

    INSTANCE;

    final UUID uuid = UUID.fromString("B61BB1E5-38AF-4D54-A04B-0823E88F96A0");
    private List<SocketBase.OnReceiveListener> mOnReceiveListeners = new ArrayList<>();
    Map<String,BluetoothClient> mBluetoothClients = new HashMap<>();
    private boolean isListening;
    private BluetoothServerSocket mServerSocket;

    public void connect(String mac) throws Exception {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null) {
            throw new Exception("设备不支持蓝牙");
        }
        if (!adapter.isEnabled()) {
            throw new Exception("蓝牙没打开");
        }
        final BluetoothDevice device = adapter.getRemoteDevice(mac);
        BluetoothClient client = mBluetoothClients.get(mac);
        if(client != null) {
            client.close();
        }
        BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid);
        socket.connect();
        client = new BluetoothClient(socket,mac,this);
        mBluetoothClients.put(mac,client);
        client.startReceive();
    }

    public BluetoothDevice getDevice(String mac) {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        BluetoothDevice device = adapter.getRemoteDevice(mac);
        return device;
    }

    public void addListener(SocketBase.OnReceiveListener listener) {
        System.out.println("setListener = " + (listener == null?"null":listener.getClass().getName()));
        if (!mOnReceiveListeners.contains(listener)) {
            mOnReceiveListeners.add(listener);
        }
    }

    public void removeListener(SocketBase.OnReceiveListener listener) {
        mOnReceiveListeners.remove(listener);
    }

    public String getMac() {
        if (mBluetoothClients.size() == 1) {
            return mBluetoothClients.values().iterator().next().mac;
        }
        return "";
    }

    public void actAsServer() {
        if (isListening) {
            return;
        }
        isListening = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
                if(adapter == null || !adapter.isEnabled()) {
                    return;
                }
                try {
                    mServerSocket = adapter.listenUsingRfcommWithServiceRecord("liuwei", UUID.fromString("B61BB1E5-38AF-4D54-A04B-0823E88F96A0"));
                    while (isListening) {
                        try{
                            BluetoothSocket socket = mServerSocket.accept();
                            String mac = socket.getRemoteDevice().getAddress();
                            BluetoothClient client = new BluetoothClient(socket,mac,BluetoothManager.this);
                            mBluetoothClients.put(mac,client);
                            client.startReceive();
                        } catch (Exception e) {
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public void close() {
        for (BluetoothClient client:mBluetoothClients.values()) {
            client.close();
        }
        isListening = false;
        if (mServerSocket != null) {
            try {
                mServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        mBluetoothClients.clear();
    }

    public void send(String mac,String text) {
        BluetoothClient client = mBluetoothClients.get(mac);
        if (client != null) {
            client.send(text);
        }
    }
    public void sendConfig(String mac,String name,String text) {
        BluetoothClient client = mBluetoothClients.get(mac);
        if (client != null) {
            client.sendConfig(name,text);
        }
    }

    public void sendConfigNames(String mac,String text) {
        BluetoothClient client = mBluetoothClients.get(mac);
        if (client != null) {
            client.sendConfigNames(text);
        }
    }

    public void sendConfigReq(String mac,final String name) {
        BluetoothClient client = mBluetoothClients.get(mac);
        if (client != null) {
            client.sendConfigReq(name);
        }
    }

    public void sendConfigsReq(String mac) {
        BluetoothClient client = mBluetoothClients.get(mac);
        if (client != null) {
            client.sendConfigsReq();
        }
    }

    @Override
    public void onReceived(String ip, short cmd, CharSequence... text) {
        for (SocketBase.OnReceiveListener listener:mOnReceiveListeners) {
            listener.onReceived(ip,cmd,text);
        }
    }

    @Override
    public void onConnect(String ip, boolean connect) {
        System.out.println("onConnect " + ip);
        if (!connect) {
            BluetoothClient client = mBluetoothClients.get(ip);
            if (client != null) {
                client.close();
            }
            mBluetoothClients.remove(ip);
        }
        for (SocketBase.OnReceiveListener listener:mOnReceiveListeners) {
            listener.onConnect(ip,connect);
        }
    }


    public class BluetoothClient extends SocketBase{
        public BluetoothSocket mSocket;
        private Lock mLock;
        private boolean isQuitReadMessage;
        public String mac;
        InputStream inputStream;
        OutputStream outputStream;

        public BluetoothClient(BluetoothSocket socket, String mac, SocketBase.OnReceiveListener listener) throws IOException {
            super(listener);
            mSocket = socket;
            this.mac = mac;
            mLock = new ReentrantLock();
            inputStream = mSocket.getInputStream();
            outputStream = mSocket.getOutputStream();
            init(outputStream,mac,mLock);
        }

        public boolean isClose() {
            return isQuitReadMessage;
        }

        public void close() {
            isQuitReadMessage = true;
            IOHelper.closeOutputStream(outputStream);
            IOHelper.closeInputStream(inputStream);
        }

        public void sendHeart() throws IOException {
            try {
                mLock.lock();
                IOHelper.sendHeart(outputStream);
            } finally {
                mLock.unlock();
            }
        }

        void startReceive() {
            mPubExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    while (!isQuitReadMessage) {
                        try {
                            Thread.sleep(500);
                            short cmd = IOHelper.readCmd(inputStream);
                            String text = receive(inputStream, mac, cmd);
                            if (text == null || text.length() == 0) {
                                continue;
                            }
                            postToUI(mac, cmd, text);

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }

        @Override
        protected void sendFileListInfo(String ip, DirectoryBean bean) {
            sendFileListInfo(bean);
        }

        @Override
        protected void sendFile(String ip, String path) {
            sendFile(path);
        }
    }
}
